/*
 * This is written by Lulu Han.
 * E-mail: locomotive_crypto@163.com
 */

#include "net_server.h"

NetServer::NetServer(size_t port):
	m_io_service(), 
	m_socket(m_io_service), // save the client object
	m_ep(tcp::v4(), port),
	m_acceptor(m_io_service, m_ep){ // define the acceptor object for waiting the conenction by the client
}

void NetServer::accept(){
	m_acceptor.accept(m_socket);
}

void NetServer::send(const char* buff, long len){
	asio::write(m_socket, 
		asio::buffer(buff, len));
}

void NetServer::send(const unsigned char* buff, long len){
	 asio::write(m_socket, 
		asio::buffer(buff, len));
}

void NetServer::send(long n){
	this->send((unsigned char*)&n, sizeof(n));
}

void NetServer::send(const NTL::ZZ& n){
	// First, send the length of the ZZ object
	this->send(NTL::NumBytes(n));
	// Second, send the real byte of ZZ
	std::vector<unsigned char> buff(NTL::NumBytes(n));
	NTL::BytesFromZZ(buff.data(), n, buff.size());
	this->send(buff.data(), buff.size());
}

void NetServer::send(const NTL::RR& n){
	std::stringstream ss;
	ss << n;
	std::string str = ss.str();
	this->send(str);
}

void NetServer::send(const std::string& str){
	long strlen = str.size();
	
	this->send(strlen);
	this->send(str.data(), strlen);
}

void NetServer::send(const std::vector<NTL::ZZ>& vzz){
	long vlen = vzz.size();
	this->send(vlen);
	for(long i = 0; i< vlen; ++i){
		this->send(vzz[i]);
	}
}

void NetServer::send(const std::vector<NTL::RR>& vrr){
	long vlen = vrr.size();
	this->send(vlen);
	for(long i = 0; i< vlen; ++i){
		this->send(vrr[i]);
	}
}

void NetServer::send(const std::vector<std::vector<NTL::ZZ>>& vvzz){
	long vvlen = vvzz.size();
	this->send(vvlen);
	for(long i = 0; i < vvlen; ++i){
		this->send(vvzz[i]);
	}
}
////////////////////////////////////////////////////////////////////////////////

void NetServer::receive(char* buff, long len){
	asio::read(m_socket, 
		asio::buffer(buff, len));
}

void NetServer::receive(unsigned char* buff, long len){
	asio::read(m_socket, 
		asio::buffer(buff, len));
}

void NetServer::receive(long& n){
	this->receive((unsigned char*)&n, sizeof(n));
}

void NetServer::receive(NTL::ZZ& n){
	long nlen;
	// First, receive the length of the ZZ object
	this->receive(nlen);
	// Second, receive the real byte of ZZ
	std::vector<unsigned char> buff(nlen);
	this->receive(buff.data(), buff.size());
	NTL::ZZFromBytes(n, buff.data(), buff.size());
}

void NetServer::receive(NTL::RR& n){
	std::string str;
	this->receive(str);
	
	std::stringstream ss;
	ss << str;
	
	ss >> n;
}

void NetServer::receive(std::string& str){
	long strlen;
	this->receive(strlen);
	str.resize(strlen);
	this->receive((char*)str.data(), strlen);
}

void NetServer::receive(std::vector<NTL::ZZ>& vzz){
	long vlen;
	this->receive(vlen);
	
	vzz.clear();
	NTL::ZZ zz;
	for(long i = 0; i < vlen; ++i){
		this->receive(zz);
		vzz.push_back(zz);
	}
}

void NetServer::receive(std::vector<NTL::RR>& vrr){
	long vlen;
	this->receive(vlen);
	
	vrr.clear();
	NTL::RR rr;
	for(long i = 0; i < vlen; ++i){
		this->receive(rr);
		vrr.push_back(rr);
	}
}

void NetServer::receive(std::vector<std::vector<NTL::ZZ>>& vvzz){
	vvzz.clear();
	
	long vvlen;
	this->receive(vvlen);
	
	for(long i = 0; i < vvlen; ++i){
		std::vector<NTL::ZZ> vzz;
		this->receive(vzz);
		vvzz.push_back(vzz);
	}
}

void NetServer::close(){
	m_socket.close();
}

void NetServer::run(){
	m_io_service.run();
}
